package org.openmore.opc.service.impl;

import com.github.pagehelper.Page;
import org.openmore.common.data.Tree;
import org.openmore.common.exception.OpenmoreException;
import org.openmore.opc.dao.PermissionMapper;
import org.openmore.opc.dao.RolePermissionMapper;
import org.openmore.opc.dto.api.PermissionDto;
import org.openmore.opc.dto.api.RolePermissionDto;
import org.openmore.opc.entity.Permission;
import org.openmore.opc.entity.Role;
import org.openmore.opc.entity.RolePermission;
import org.openmore.opc.entity.User;
import org.openmore.opc.entity.enums.UserType;
import org.openmore.opc.framework.MyThreadLocalConfig;
import org.openmore.opc.framework.ReferencedFieldProcessor;
import org.openmore.opc.service.PermissionService;
import org.openmore.opc.service.RoleService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import tk.mybatis.mapper.entity.Example;

import java.util.*;

@Service
public class PermissionServiceImpl extends BaseServiceImpl implements PermissionService {
    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private PermissionMapper permissionMapper;

    @Autowired
    private RolePermissionMapper rolePermissionMapper;

    @Autowired
    private ReferencedFieldProcessor processor;


    @Autowired
    private RoleService roleService;

    /**
     * 根据id获得实体对象
     *
     * @param id
     */
    @Override
    public Permission getEntityById(String id) {
        Example example = new Example(Permission.class);
        example.createCriteria().andEqualTo("id", id);
        return permissionMapper.selectOneByExample(example);
    }

    /**
     * 根据id获得DTO对象
     *
     * @param id
     */
    @Override
    public PermissionDto getDtoById(String id) {
        PermissionDto dto = new PermissionDto();
        Permission permission = this.getEntityById(id);
        if (permission == null) {
            return null;
        }
        BeanUtils.copyProperties(permission, dto);
        return dto;
    }

    /**
     * 获得权限树
     *
     * @return
     */
    @Override
    public List<PermissionDto> getPermissionTree() {
        User user = MyThreadLocalConfig.getUser();
        if (user == null) {
            throw new OpenmoreException("需要登录权限，请重新登录");
        }
        List<Permission> entityList = null;
//        Example example = new Example(Permission.class);
//        example.createCriteria().andEqualTo("deleted", false);

//      根据固定角色找对应的权限
        if (user.getUserType() == UserType.STAFF) {
            Role rootRole = roleService.getEntityByCode(Role.ROLE_STAFF);
            List<Role> roles = new ArrayList<>();
            roles.add(rootRole);
            entityList = getPermissionsByRoles(roles);
//            entityList = permissionMapper.selectByExample(example);
        } else if (user.getUserType() == UserType.ROOT) {
            Role rootRole = roleService.getEntityByCode(Role.ROLE_ROOT);
            List<Role> roles = new ArrayList<>();
            roles.add(rootRole);
            entityList = getPermissionsByRoles(roles);
//            entityList = permissionMapper.selectByExample(example);
        } else if (user.getUserType() == UserType.MANAGER) {
            Role rootRole = roleService.getEntityByCode(Role.ROLE_MANAGER);
            List<Role> roles = new ArrayList<>();
            roles.add(rootRole);
            entityList = getPermissionsByRoles(roles);
//            entityList = permissionMapper.selectByExample(example);
        } else {
            // 其它角色返回null
            return null;
        }

        List<PermissionDto> dtoList = new ArrayList<>();
        for (Permission permission : entityList) {
            PermissionDto dto = new PermissionDto();
            BeanUtils.copyProperties(permission, dto);
            dtoList.add(dto);
        }

        Tree tree = Tree.create(dtoList);
        List<PermissionDto> rootList = tree.getTree();
        if (rootList == null || rootList.size() == 0) {
            throw new OpenmoreException("权限配置出错:找不到根节点");
        }
        return rootList;
    }

    /**
     * 获得所有记录
     *
     * @return
     */
    @Override
    public List<PermissionDto> selectAll(String type, String name) {
        Example example = new Example(Permission.class);
        Example.Criteria criteria = example.createCriteria();
        if ("parent".equals(type)) {
            criteria.andEqualTo("parentId", "");
        } else if ("children".equals(type)){
            criteria.andNotEqualTo("parentId", "");
        }
        if (!StringUtils.isEmpty(name)) {
            name = "%" + name + "%";
            criteria.andLike("name", name);
        }
        criteria.andEqualTo("deleted", false);
        List<Permission> entityList = permissionMapper.selectByExample(example);
        Page<PermissionDto> dtoList = new Page<>();
        if (CollectionUtils.isEmpty(entityList)) {
            return dtoList;
        }
        if (entityList instanceof Page) {
            BeanUtils.copyProperties(entityList, dtoList);
            dtoList.clear();
        }
        for (Permission permission : entityList) {
            PermissionDto dto = new PermissionDto();
            BeanUtils.copyProperties(permission, dto);
            dtoList.add(dto);
        }
        processor.process(dtoList);
        return dtoList;
    }

    /**
     * 带UUID的插入
     * 所有的插入数据，都要调用这个实现
     *
     * @param dto
     */
    public PermissionDto insert(PermissionDto dto) {
        Permission entity = new Permission();
        BeanUtils.copyProperties(dto, entity);
        beforeInsert(entity);
        permissionMapper.insert(entity);
        insertLog("insert permission");
        User loginUser = MyThreadLocalConfig.getUser();
        if(loginUser != null) {
            RolePermission rolePermission = new RolePermission();
            rolePermission.setPermissionId(entity.getId());
            rolePermission.setRoleId(loginUser.getRoleId());
            rolePermissionMapper.insert(rolePermission);
            insertLog("insert 角色与权限的关系");
        }
        dto.setId(entity.getId());
        return dto;
    }

    /**
     * 删除指定id的数据
     */
    public void deleteById(String id) {
        if(StringUtils.isEmpty(id)){
            throw new OpenmoreException(4001, "id不能为空");
        }
        Permission entity = this.getEntityById(id);
        if (entity != null) {
            Example example = new Example(Permission.class);
            example.createCriteria().andEqualTo("id", id);
            entity.setDeleted(true);
            permissionMapper.updateByExampleSelective(entity, example);
            insertLog("delete permission");
            example = new Example(RolePermission.class);
            example.createCriteria().andEqualTo("permissionId", id);
            rolePermissionMapper.deleteByExample(example);
            insertLog("删除角色与权限的关系");
        }
    }

    /**
     * 修改数据
     */
    public void update(PermissionDto dto) {
        if (null == dto) {
            throw new OpenmoreException(4001, "参数不能为空");
        }
        if(StringUtils.isEmpty(dto.getId())){
            throw new OpenmoreException(4001, "id不能为空");
        }
        Permission entity = new Permission();
        BeanUtils.copyProperties(dto, entity);
        Example example = new Example(Permission.class);
        example.createCriteria().andEqualTo("id", entity.getId());
        beforeUpdate(entity);
        permissionMapper.updateByExampleSelective(entity, example);
        insertLog("update permission");
    }

    /**
     * 根据权限id列表，返回对应的顺序菜单列表
     *
     * @return
     */
    public List<PermissionDto> findMenuByPermissions(List<Permission> permissions) {
        if (permissions == null) {
            return null;
        }

        // 获得所有的权限，按顺序排列
        Example example = new Example(Permission.class);
        example.createCriteria().andEqualTo("deleted", false);
        example.setOrderByClause("sort_order desc");
        List<Permission> allPermission = permissionMapper.selectByExample(example);
//      权限列表
        HashMap<String, PermissionDto> allPerMap = new HashMap<>();
        for (Permission p : allPermission) {
            PermissionDto dto = new PermissionDto();
            BeanUtils.copyProperties(p, dto);
            allPerMap.put(p.getId(), dto);
        }
//      顶级菜单列表
        LinkedHashMap<String, PermissionDto> menuMap = new LinkedHashMap<>();
//      从二级子菜单里，获得上级菜单列表，并且将二级菜单添加到上级菜单里
        for (Permission perm : permissions) {
//          顶级菜单列表里没有时，添加新顶级菜单
            if(StringUtils.isEmpty(perm.getParentId())) {
                // 顶级权限不存在，添加
                if(menuMap.get(perm.getId()) == null) {
                    PermissionDto  dto = allPerMap.get(perm.getId());
                    dto.children = new ArrayList<>();
                    menuMap.put(perm.getId(), allPerMap.get(perm.getId()));
                }
            }
            // 权限有父权限
            PermissionDto dto = menuMap.get(perm.getParentId());
            // 父权限没有，添加父权限
            if(dto == null) {
                dto = allPerMap.get(perm.getParentId());
                if(dto != null) {
                    dto.children = new ArrayList<>();
                    menuMap.put(dto.getId(), dto);
                    dto.children.add(allPerMap.get(perm.getId()));
                }
            } else {
                Object node = allPerMap.get(perm.getId());
                // fix bug 删除的节点导致菜单不显示的bug
                if(node != null) {
                    dto.children.add(allPerMap.get(perm.getId()));
                }
            }
        }
        List<PermissionDto> resultList = new ArrayList<>();
        for(Map.Entry<String, PermissionDto> entry : menuMap.entrySet()){
            resultList.add(entry.getValue());
        }
        return resultList;
    }


    /**
     * 根据角色列表获得对应的权限列表
     * ############################################################################
     * # 仅在配置shiro权限时使用，其它时候，使用getPermissionsByStaffId，直接获得用户权限
     * ############################################################################
     *
     * @param roleList
     * @return
     */
    public List<Permission> getPermissionsByRoles(List<Role> roleList) {
        if (CollectionUtils.isEmpty(roleList)) {
            return null;
        }
        String roleIds = "";
        for (Role role : roleList) {
            if (null != role && !StringUtils.isEmpty(role.getId())) {
                roleIds += role.getId() + ",";
            }
        }

        if (StringUtils.isEmpty(roleIds)) {
            return null;
        }
        return permissionMapper.getPermissionsByRoleIds(roleIds);
    }

    /**
     * 根据角色id获得该角色拥有的权限
     *
     * @return
     */
    public List<RolePermissionDto> getGrantedPermissionByStaffId(String roleId) {
        Example example = new Example(RolePermission.class);
        example.createCriteria().andEqualTo("roleId", roleId);
        List<RolePermission> entities = rolePermissionMapper.selectByExample(example);
        List<RolePermissionDto> resultList = new ArrayList<>();
        for (RolePermission rp : entities) {
            RolePermissionDto dto = new RolePermissionDto();
            BeanUtils.copyProperties(rp, dto);
            resultList.add(dto);
        }
        processor.process(resultList);
        return resultList;
    }

    /**
     * 根据员工id获得所有权限列表
     *
     * @param staffId
     * @return
     */
    public List<Permission> getPermissionsByStaffId(String staffId) {
        if (StringUtils.isEmpty(staffId)) {
            return null;
        }
        return permissionMapper.getPermissionsByStaffId(staffId);
    }
}
